package com.rxyb.auth.config;

import com.rxyb.security.exception.BusiOAuth2WebResponseExceptionTranslator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import javax.annotation.Resource;
import javax.sql.DataSource;

/**
 * @author YJH
 * @version 1.0
 * @description 授权服务器
 * @date 2020/5/20  14:15
 */
@Configuration
@EnableAuthorizationServer
public class AuthServerConfiguration extends AuthorizationServerConfigurerAdapter {


    final AuthenticationManager authenticationManager;
    final RedisConnectionFactory redisConnectionFactory;
    final UserDetailsService userDetailsService;
    // oauth2 异常处理
    final BusiOAuth2WebResponseExceptionTranslator busiOAuth2WebResponseExceptionTranslator;

    @Resource
    private DataSource dataSource;


    public AuthServerConfiguration(AuthenticationManager authenticationManager, RedisConnectionFactory redisConnectionFactory, UserDetailsService userDetailsService, BusiOAuth2WebResponseExceptionTranslator busiOAuth2WebResponseExceptionTranslator) {
        this.authenticationManager = authenticationManager;
        this.redisConnectionFactory = redisConnectionFactory;
        this.userDetailsService = userDetailsService;
        this.busiOAuth2WebResponseExceptionTranslator = busiOAuth2WebResponseExceptionTranslator;
    }

    /**
     * 该函数配置oauth2 生成token 得配置 共有四种方式
     * 授权码（authorization-code）
     * 隐藏式（implicit）
     * 密码式（password）
     * 客户端凭证（client credentials）
     *
     * @param clients
     * @throws Exception
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientDetails());

    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                .tokenStore(new RedisTokenStore(redisConnectionFactory))
                .authenticationManager(authenticationManager);
        // 处理 ExceptionTranslationFilter 抛出的异常
        endpoints.exceptionTranslator(busiOAuth2WebResponseExceptionTranslator);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        //允许表单认证
        oauthServer.tokenKeyAccess("permitAll()") //允许所有人请求令牌
                .checkTokenAccess("permitAll()") //已验证的客户端才能请求check_token端点
                .allowFormAuthenticationForClients();
    }

    /**
     * 客户端从数据库读取
     *
     * @return
     */
    @Bean
    public ClientDetailsService clientDetails() {
        return new JdbcClientDetailsService(dataSource);
    }
}
